---
title: SAIF.Business.Claim.Legal business rules
summary: Enumerated business rules with per-rule trigger, enforcement, and outcomes for the legal case-management domain.
status: draft
owner: SAIF Case Management team
last_reviewed: 2026-08-25
library: SAIF.Business.Claim.Legal
reference_type: embedded
---

# SAIF.Business.Claim.Legal business rules

This page captures business rules enforced by this library. Rule identifiers use a library-specific prefix followed
by a sequence number (see the individual rule headings below) assigned during Stage 1 analysis (TSK004) and are
preserved as-is for cross-reference stability with operations and SQL pages in this document set.

## BR-CLM-LGL-001 Case cost date ranges must be valid

| Field | Value |
| --- | --- |
| **Statement** | Case cost authorized date and service dates must fall within valid ranges, and the service "to" date must be on/after the service "from" date. |
| **Trigger** | Setting/validating `AuthorizedDate`, `ServiceFromDate`, `ServiceToDate` on `clsCaseCost`. |
| **Enforcement** | `Rule_AuthorizedDateMax/Min`, `Rule_ServiceFromDateMax/Min`, `Rule_ServiceToDateMax`, `Rule_ServiceDatesValid` (~lines 522-577) |
| **Outcome** | Broken rule raised; save blocked until dates are valid. |
| **Tables** | [CASE_COST](database-tables.md#case_cost) |
| **SQL** | [DB-CLL-002](sql/SQL-002-casecost.md), [DB-CLL-003](sql/SQL-003-casecost.md) |
| **Source** | `SAIF.Business.Claim.Legal\LegalNet\clsCaseCost.vb` |

---

## BR-CLM-LGL-002 Case cost entry requires a payee

| Field | Value |
| --- | --- |
| **Statement** | A case cost entry must have a payee (firm or name). |
| **Trigger** | Saving a `clsCaseCost`. |
| **Enforcement** | `Rule_PayeeFirm`, `Rule_PayeeName` (~lines 573-586) |
| **Outcome** | Broken rule raised if no payee identified. |
| **Tables** | [CASE_COST](database-tables.md#case_cost) |
| **SQL** | [DB-CLL-002](sql/SQL-002-casecost.md), [DB-CLL-003](sql/SQL-003-casecost.md) |
| **Source** | `SAIF.Business.Claim.Legal\LegalNet\clsCaseCost.vb` |

---

## BR-CLM-LGL-003 Case cost entry requires service code, authorizer, and canceller

| Field | Value |
| --- | --- |
| **Statement** | A case cost entry requires a valid service code, authorizer, and (if cancelled) canceller. |
| **Trigger** | Saving a `clsCaseCost`. |
| **Enforcement** | `Rule_ServiceCode`, `Rule_Authorizer`, `Rule_CancelledBy` (~lines 584-586+) |
| **Outcome** | Broken rule raised until required codes are populated. |
| **Tables** | [CASE_COST](database-tables.md#case_cost) |
| **SQL** | [DB-CLL-002](sql/SQL-002-casecost.md), [DB-CLL-003](sql/SQL-003-casecost.md) |
| **Source** | `SAIF.Business.Claim.Legal\LegalNet\clsCaseCost.vb` |

---

## BR-CLM-LGL-004 Case search input must match search-type format

| Field | Value |
| --- | --- |
| **Statement** | Case search input must match the format required by the selected search type (claim number = 7 chars; SSN = 11 chars incl. dashes; policy number length in {1-6, 9}; worker-name search requires last name; check-number search requires a check number). |
| **Trigger** | User submits `clsCaseSearchCriteria` for a search. |
| **Enforcement** | `LegalNet\clsCaseSearchCriteria.vb` (~lines 24-50) |
| **Outcome** | Search rejected/flagged invalid until criteria conform. |
| **Source** | `SAIF.Business.Claim.Legal\LegalNet\clsCaseSearchCriteria.vb` |

---

## BR-CLM-LGL-005 Non-single-row CRUD result is treated as a failure

| Field | Value |
| --- | --- |
| **Statement** | An `Insert`/`Update`/`Delete`/save operation that affects zero or more-than-one row is treated as a concurrency/failure condition. |
| **Trigger** | Any `After*` lifecycle method across the majority of `LegalNet` entities (`clsAcknowledge`, `clsAppeal`(+Extension), `clsCaseNote`, `clsCaseOutcome`, `clsCaseStatusHistory`, `clsHearingLocationInfo`, `clsLegalCase`, `clsLegalCaseEvaluation`, `clsLegalFileLocation`, `clsLegalSchedule`, `clsMailDate`, `clsOtherLegalParty`, `clsOutcomeIssue`, `clsOutcomeStaff`, `clsRequestIssue`). |
| **Enforcement** | Respective `AfterInsert`/`AfterUpdate`/`AfterDelete` methods; pattern: `If RowsAffected <> 1 Then AddErrorMessage("UpdateError","Update Failed")`. |
| **Outcome** | Business object reports a broken rule/error; caller sees save failure and the transaction is not treated as successful. |
| **Source** | `SAIF.Business.Claim.Legal\LegalNet\` (multiple files, see Statement) |

---

## BR-CLM-LGL-006 Attorney policy assignment requires a valid policy

| Field | Value |
| --- | --- |
| **Statement** | An `AttorneyPolicyAssignment.PolicyNumber` must reference a valid, existing policy when the assignment is dirty. |
| **Trigger** | Editing/saving `clsAttorneyPolicyAssignment`. |
| **Enforcement** | `Rule_ValidPolicy` (~lines 499-503) |
| **Outcome** | Broken rule "Must enter a valid policy number." until a valid policy is set. |
| **Tables** | [ATTORNEY_POLICY_ASSIGNMENT](database-tables.md#attorney_policy_assignment) |
| **Source** | `SAIF.Business.Claim.Legal\TableMaint\clsAttorneyWorkerAssignment.vb` |

---

## BR-CLM-LGL-007 Attorney policy assignment requires a primary attorney

| Field | Value |
| --- | --- |
| **Statement** | An `AttorneyPolicyAssignment` must designate a primary attorney (employee ID present) when dirty. |
| **Trigger** | Editing/saving `clsAttorneyPolicyAssignment`. |
| **Enforcement** | `Rule_ValidPrimary` |
| **Outcome** | Broken rule "Must select a primary attorney." |
| **Tables** | [ATTORNEY_POLICY_ASSIGNMENT](database-tables.md#attorney_policy_assignment) |
| **Source** | `SAIF.Business.Claim.Legal\TableMaint\clsAttorneyWorkerAssignment.vb` |

---

## BR-CLM-LGL-008 Attorney profile requires attorney, type, and valid date range

| Field | Value |
| --- | --- |
| **Statement** | An attorney profile requires an attorney (employee id), a type code, and a valid effective/expiration date range (expiration ≥ effective, or expiration unset). |
| **Trigger** | Saving `clsAttorneyProfile`. |
| **Enforcement** | `Rule_ValidProfileEmplid`, `Rule_ValidTypeCode`, `Rule_ValidBeginDate`, `Rule_ValidEndDate` |
| **Outcome** | Broken rule raised for missing/invalid attorney, type, or date range. |
| **Source** | `SAIF.Business.Claim.Legal\TableMaint\clsAttorneyProfile.vb` |

---

## BR-CLM-LGL-009 Duplicate attorney profile rows are rejected

| Field | Value |
| --- | --- |
| **Statement** | Within a dirty parent collection, the same attorney employee ID cannot appear on more than one `clsAttorneyProfile` sibling (duplicate-attorney check). |
| **Trigger** | Adding/editing an attorney profile row in a collection. |
| **Enforcement** | `Rule_DuplicateAttorney` (~lines 499-523) |
| **Outcome** | Broken rule "Duplicate Attorney record." — prevents duplicate attorney profile rows. |
| **Source** | `SAIF.Business.Claim.Legal\TableMaint\clsAttorneyProfile.vb` |

---

## BR-CLM-LGL-010 Attorney schedule entry requires attorney, reason, and duration

| Field | Value |
| --- | --- |
| **Statement** | An attorney schedule entry requires an attorney, a schedule-reason (type) code, and a duration code. |
| **Trigger** | Saving `clsAttorneySchedule`. |
| **Enforcement** | `Rule_ValidAttorney`, `Rule_ValidScheduleType`, `Rule_ValidDuration` |
| **Outcome** | Broken rule raised until attorney/reason/duration selected. |
| **Tables** | [ATTORNEY_SCHEDULE](database-tables.md#attorney_schedule) |
| **Source** | `SAIF.Business.Claim.Legal\TableMaint\clsAttorneyWorkerAssignment.vb` |

---

## BR-CLM-LGL-011 Attorney schedule dates must be valid and non-past

| Field | Value |
| --- | --- |
| **Statement** | An attorney schedule entry's effective and expiration dates must each be today or later, and expiration must be on/after effective. |
| **Trigger** | Saving `clsAttorneySchedule`. |
| **Enforcement** | `Rule_ValidEffDate`, `Rule_ValidExpDate`, `Rule_ValidExpDateAfterEffDate` (~lines 347-362) |
| **Outcome** | Broken rule raised for past/out-of-order dates. |
| **Tables** | [ATTORNEY_SCHEDULE](database-tables.md#attorney_schedule) |
| **Source** | `SAIF.Business.Claim.Legal\TableMaint\clsAttorneyWorkerAssignment.vb` |

---

## BR-CLM-LGL-012 Hearing location requires valid code, name, state, and city

| Field | Value |
| --- | --- |
| **Statement** | A hearing-location record must have a non-blank location code and location name; if a state is provided it must be ≤2 characters and pass a lookup against `ALL_STATES`/`NCCI_STATE_CODE`; city must not contain digits or special characters. |
| **Trigger** | Saving `clsHearingLocation`. |
| **Enforcement** | `Rule_ValidLocation`, `Rule_ValidLocationName`, `Rule_ValidState`, `Rule_ValidCity`, `ValidateState()` |
| **Outcome** | Broken rule raised for missing/invalid location data. |
| **Tables** | [HEARING_LOCATION](database-tables.md#hearing_location), [ALL_STATES](database-tables.md#all_states) |
| **SQL** | [DB-CLL-063](sql/SQL-063-hearinglocation.md) |
| **Source** | `SAIF.Business.Claim.Legal\TableMaint\clsHearingLocation.vb` |

---

## BR-CLM-LGL-013 Hearing location cannot be deleted while referenced by schedule rows

| Field | Value |
| --- | --- |
| **Statement** | A hearing location cannot be deleted while schedule rows reference it. |
| **Trigger** | Deleting `clsHearingLocation`. |
| **Enforcement** | `CanDeleteLocation(inLocationSeq As Decimal) As Boolean` |
| **Outcome** | Delete blocked/denied when dependent schedule rows exist. |
| **Tables** | [HEARING_LOCATION](database-tables.md#hearing_location), [SCHEDULE](database-tables.md#schedule) |
| **SQL** | [DB-CLL-062](sql/SQL-062-hearinglocation.md) |
| **Source** | `SAIF.Business.Claim.Legal\TableMaint\clsHearingLocation.vb` |

---

## BR-CLM-LGL-014 Legal person requires last and first name

| Field | Value |
| --- | --- |
| **Statement** | A legal person record requires both last name and first name. |
| **Trigger** | Saving `clsLegalPerson`. |
| **Enforcement** | `Rule_ValidName` (~line 245) |
| **Outcome** | Broken rule "Please enter a value in the Last Name and First Name fields." |
| **Tables** | [LEGAL_PERSON](database-tables.md#legal_person) |
| **Source** | `SAIF.Business.Claim.Legal\TableMaint\clsLegalPerson.vb` |

---

## BR-CLM-LGL-015 Legal person cannot be deleted while referenced

| Field | Value |
| --- | --- |
| **Statement** | A legal person cannot be deleted while referenced by `attorney_conflict`, `outcome_staff`, or `legal_person_type`. |
| **Trigger** | Deleting `clsLegalPerson`. |
| **Enforcement** | `CanDeleteLegalPerson(inPersonSeq As Decimal) As Boolean` |
| **Outcome** | Delete blocked when references exist in dependent tables. |
| **Tables** | [LEGAL_PERSON](database-tables.md#legal_person), [ATTORNEY_CONFLICT](database-tables.md#attorney_conflict), [OUTCOME_STAFF](database-tables.md#outcome_staff), [LEGAL_PERSON_TYPE](database-tables.md#legal_person_type) |
| **SQL** | [DB-CLL-061](sql/SQL-061-legalperson.md) |
| **Source** | `SAIF.Business.Claim.Legal\TableMaint\clsLegalPerson.vb` |

---

## BR-CLM-LGL-016 Legal-person-type link requires person and type code

| Field | Value |
| --- | --- |
| **Statement** | A legal-person-type link requires a selected legal person and a type code. |
| **Trigger** | Saving `clsLegalPersonType`. |
| **Enforcement** | `Rule_ValidName`, `Rule_ValidType` (~lines 499-503) |
| **Outcome** | Broken rule raised until both are selected. |
| **Tables** | [LEGAL_PERSON_TYPE](database-tables.md#legal_person_type) |
| **Source** | `SAIF.Business.Claim.Legal\TableMaint\clsLegalPersonType.vb` |

---

## BR-CLM-LGL-017 Other firm state city must be valid

| Field | Value |
| --- | --- |
| **Statement** | An "other firm" record's state (if provided) must be ≤2 characters and pass state validation; city must not contain digits/special characters. |
| **Trigger** | Saving `clsOtherFirm`. |
| **Enforcement** | `Rule_ValidState`, `Rule_ValidCity`, `ValidateState()` (~lines 441-448) |
| **Outcome** | Broken rule raised for invalid state/city. |
| **Tables** | [OTHER_FIRM](database-tables.md#other_firm), [ALL_STATES](database-tables.md#all_states) |
| **SQL** | [DB-CLL-064](sql/SQL-064-otherfirm.md) |
| **Source** | `SAIF.Business.Claim.Legal\TableMaint\clsOtherFirm.vb` |

---

## BR-CLM-LGL-018 Out-of-town rotation assignment dates must be valid and non-past

| Field | Value |
| --- | --- |
| **Statement** | An out-of-town rotation assignment's effective/expiration dates must each be today or later, and expiration must be on/after effective. |
| **Trigger** | Saving `clsOutOFTownRotationAssgn`. |
| **Enforcement** | `Rule_ValidEffDate`, `Rule_ValidExpDate`, `Rule_ValidExpDateAfterEffDate` (~lines 347-362) |
| **Outcome** | Broken rule raised for past/out-of-order dates. |
| **Tables** | [OUT_OF_TOWN_ROTATION_ASSGN](database-tables.md#out_of_town_rotation_assgn) |
| **Source** | `SAIF.Business.Claim.Legal\TableMaint\clsOutOFTownRotationAssgn.vb` |

---

## BR-CLM-LGL-019 File location falls back to a sentinel value on lookup failure

| Field | Value |
| --- | --- |
| **Statement** | `clsLegalFileLocation` falls back to a literal `"Bad data"` value when an employee-ID lookup for the file-location assignee fails.* |
| **Trigger** | Setting the employee-linked property on `clsLegalFileLocation`. |
| **Enforcement** | Property setter (~line 75) |
| **Outcome** | Property/UI shows sentinel "Bad data" instead of throwing, signalling a data-quality problem to the user.* |
| **Tables** | [LEGAL_FILE_LOCATION](database-tables.md#legal_file_location) |
| **Source** | `SAIF.Business.Claim.Legal\LegalNet\clsLegalFileLocation.vb` |

---

## BR-CLM-LGL-020 Letter hearing date renders empty rather than a default value

| Field | Value |
| --- | --- |
| **Statement** | `clsLetterRequest.HearingDate` renders as an empty string rather than a default `DateTime` when unset. |
| **Trigger** | Rendering hearing date on a letter request. |
| **Enforcement** | `Print\clsLetterRequest.vb` (~line 299) |
| **Outcome** | Avoids printing a meaningless default date on generated letters. |
| **Source** | `SAIF.Business.Claim.Legal\Print\clsLetterRequest.vb` |

---

## BR-CLM-LGL-021 Policy short name truncation and special-case substitution

| Field | Value |
| --- | --- |
| **Statement** | `clsLetterRequest.PolicyShortName` truncates policy name to 20 characters and substitutes a special-cased value for `"STATE OF OREGON"`. |
| **Trigger** | Formatting policy name for a printed letter. |
| **Enforcement** | `Print\clsLetterRequest.vb` (~lines 573-591) |
| **Outcome** | Printed letter shows a fitting/short policy name. |
| **Source** | `SAIF.Business.Claim.Legal\Print\clsLetterRequest.vb` |

---

## BR-CLM-LGL-022 State-entity attorney title override

| Field | Value |
| --- | --- |
| **Statement** | When `StateEntityFlag = "Y"`, the SAIF attorney's displayed title is overridden to "Special Assistant Attorney General". |
| **Trigger** | Resolving attorney info for a letter (`GetSaifAttorney`). |
| **Enforcement** | `Print\clsLetterRequest.vb` (~lines 1010-1016) |
| **Outcome** | Printed letter shows the state-entity-specific title instead of the standard title. |
| **Source** | `SAIF.Business.Claim.Legal\Print\clsLetterRequest.vb` |

---

## BR-CLM-LGL-023 Worker-attorney display fallback chain

| Field | Value |
| --- | --- |
| **Statement** | Worker-attorney display falls back from attorney name → firm name → worker name when the preferred field is empty. |
| **Trigger** | Resolving worker's attorney for a letter (`GetWorkerAttorney`). |
| **Enforcement** | `Print\clsLetterRequest.vb` (~lines 1055-1061) |
| **Outcome** | Printed letter always shows a usable attorney/contact label. |
| **Source** | `SAIF.Business.Claim.Legal\Print\clsLetterRequest.vb` |

---

## BR-CLM-LGL-024 Attorney schedule suppresses non-Production Exchange sync

| Field | Value |
| --- | --- |
| **Statement** | `clsAttorneySchedule` suppresses calendar (Exchange) sync when the application environment is not Production. |
| **Trigger** | Saving `clsAttorneySchedule` (`OnSave`). |
| **Enforcement** | `TableMaint\clsAttorneySchedule.vb` (~line 239) |
| **Outcome** | Non-production saves persist the schedule row without pushing an Exchange calendar update. |
| **Tables** | [ATTORNEY_SCHEDULE](database-tables.md#attorney_schedule) |
| **Source** | `SAIF.Business.Claim.Legal\TableMaint\clsAttorneyWorkerAssignment.vb` |

---

## BR-CLM-LGL-025 Consolidation schedule non-Production behavior suppression

| Field | Value |
| --- | --- |
| **Statement** | `clsConsolidations`/`clsLegalSchedule` similarly suppress a non-production-only behavior based on `AppGlobal.EnvironmentService.GetApplicationEnvironment()`.* |
| **Trigger** | Saving `clsCaseConsolidation`/`clsLegalSchedule`. |
| **Enforcement** | `LegalNet\clsConsolidations.vb` (~lines 264, 466); `LegalNet\clsLegalSchedule.vb` (~lines 535, 560) |
| **Outcome** | Behavior differs between Production and non-Production environments (exact non-prod behavior not fully traced from excerpt).* |
| **Tables** | [CONSOLIDATED_CASE](database-tables.md#consolidated_case), [LEGAL_SCHEDULE / SCHEDULE (proc target unclear)](database-tables.md#legal_schedule-schedule-(proc-target-unclear)) |
| **Source** | `SAIF.Business.Claim.Legal\LegalNet\clsConsolidations.vb`, `SAIF.Business.Claim.Legal\LegalNet\clsLegalSchedule.vb` |

---

## Inherited business rules

Rules in this section originate from base classes or services provided by dependency framework libraries. They are
enforced by inherited behavior, not by code in this library. The originating class and library are recorded in each
rule's **Origin** field.

## INH-CLL-001 Retrieve-only criteria suppresses write SQL

| Field | Value |
| --- | --- |
| **Statement** | Objects deriving from `clsRetrieveOnlyBusinessCriteria` automatically suppress `InsertSQL`/`UpdateSQL`/`DeleteSQL` — only retrieve operations are permitted.† |
| **Trigger** | Any CRUD attempt against a retrieve-only-derived business object (e.g., `clsHearingLocationInfo`, `mdlCodeTables` lookup classes). |
| **Enforcement** | `clsRetrieveOnlyBusinessCriteria` base class behavior† |
| **Outcome** | Write attempts against retrieve-only objects fail/throw rather than executing SQL. |
| **Origin** | `SAIF.Framework.Core` — `clsRetrieveOnlyBusinessCriteria` |
| **Source** | Retrieved from indexed documentation via Legends CLI |

---

## INH-CLL-002 API criteria SQL properties are always empty by design

| Field | Value |
| --- | --- |
| **Statement** | Objects deriving from `clsBusinessApiCriteriaBase` always return empty SQL for `IBusinessCriteria` properties by design — data access is delegated to a REST API client instead of direct SQL.† |
| **Trigger** | Any CRUD attempt against an API-criteria-derived business object (e.g., LegalApi-consuming classes such as `clsFindCase`, `clsAcknowledge`, `clsBoardLog`, `clsAttorneyMessages`). |
| **Enforcement** | `clsBusinessApiCriteriaBase` base class behavior† |
| **Outcome** | No SQL is executed for these objects in this library; the actual data access occurs in the external LegalApi service. |
| **Origin** | `SAIF.Framework.Core` — `clsBusinessApiCriteriaBase` |
| **Source** | Retrieved from indexed documentation via Legends CLI |

---

## Flagged findings

<!-- Non-lifecycle flagged findings surfaced by the Stage 1b DB analysis, retained here for visibility per user instruction. -->

### FLAG-CLL-001 Duplicate business objects target `HEARING_LOCATION`

| Field | Value |
| --- | --- |
| **Statement** | Two distinct business objects target the `HEARING_LOCATION` table for different use-cases: `clsHearingLocationInfo` (LegalNet, case-facing read-only lookup) and `clsHearingLocation` (TableMaint, reference-data maintenance with full CRUD). This duplication was flagged by the Stage 1b database analysis (TSK1B-002 §1) and by [architecture.md](architecture.md#design-constraints). |
| **Trigger** | n/a (structural/architectural observation, not a runtime trigger). |
| **Enforcement** | n/a — this is an architectural duplication flag, not an enforced rule. |
| **Outcome** | Two independent code paths must be kept in sync for any schema change to `HEARING_LOCATION`; a discrepancy risk exists between the read-only and maintenance paths. |
| **Tables** | [HEARING_LOCATION](database-tables.md#hearing_location) |
| **Source** | `SAIF.Business.Claim.Legal\LegalNet\clsHearingLocationInfo.vb`, `SAIF.Business.Claim.Legal\TableMaint\clsHearingLocation.vb` |

### FLAG-CLL-002 `ValidateState` builds SQL via non-parameterized string concatenation (SQL-injection risk)

| Field | Value |
| --- | --- |
| **Statement** | The `ValidateState()` ad-hoc query in both `clsHearingLocation` and `clsOtherFirm` builds SQL via raw string concatenation of caller-suppliable input (`"SELECT NCCI_STATE_CODE from ALL_STATES where STATE = '" & State & "'"`) rather than a bind parameter. This is a non-parameterized query and a potential SQL-injection surface, flagged by the Stage 1b database analysis (TSK1B-002 §1.1) for security review. |
| **Trigger** | Validating a state code as part of [BR-CLM-LGL-012](#br-clm-lgl-012-hearing-location-requires-valid-code%2C-name%2C-state%2C-and-city) (hearing location) or [BR-CLM-LGL-017](#br-clm-lgl-017-other-firm-state-city-must-be-valid) (other firm). |
| **Enforcement** | `TableMaint\clsHearingLocation.vb`, `TableMaint\clsOtherFirm.vb` (`ValidateState()`) |
| **Outcome** | Potential SQL-injection exposure if the `State` input is not otherwise constrained upstream (e.g., by a bounded dropdown); recommended for a follow-up security review. |
| **Tables** | [ALL_STATES](database-tables.md#all_states) |
| **SQL** | [DB-CLL-063](sql/SQL-063-hearinglocation.md), [DB-CLL-064](sql/SQL-064-otherfirm.md) |
| **Source** | `SAIF.Business.Claim.Legal\TableMaint\clsHearingLocation.vb`, `SAIF.Business.Claim.Legal\TableMaint\clsOtherFirm.vb` |

---

## BR-CLM-LGL-026 Legal case search falls through case number hierarchy

| Field | Value |
| --- | --- |
| **Statement** | `pk80001_legalnet.findCase` searches by `wcb_num` first, then by `dcbs_num` only when the input length is 7 or less, then by `owcp_num`, `oalj_num`, `brb_num`, and finally by `APPEAL.appeal_num`. |
| **Trigger** | Caller invokes the Oracle search routine with a case-number-like value. |
| **Enforcement** | `WCIS_DBA.pk80001_legalnet.findCase` |
| **Outcome** | The first matching identifier path determines the returned legal-case result set. |
| **Tables** | [LEGAL_CASE](database-tables.md#legal_case), [APPEAL](database-tables.md#appeal) |
| **Source** | Oracle retrieval JSON `pk80001_legalnet.json` (`findCase`) |

---

## BR-CLM-LGL-027 Case status propagates to consolidated secondary cases

| Field | Value |
| --- | --- |
| **Statement** | Updating a primary legal-case status also updates every secondary case linked through `CONSOLIDATED_CASE`. |
| **Trigger** | `pk80001_legalnet.updateCaseStatus` runs. |
| **Enforcement** | `WCIS_DBA.pk80001_legalnet.updateCaseStatus` |
| **Outcome** | Primary and secondary consolidated cases carry the same status and audit values. |
| **Tables** | [LEGAL_CASE](database-tables.md#legal_case), [CONSOLIDATED_CASE](database-tables.md#consolidated_case) |
| **Source** | Oracle retrieval JSON `pk80001_legalnet.json` (`updateCaseStatus`) |

---

## BR-CLM-LGL-028 Appeal deletion cascades schedule and state cleanup

| Field | Value |
| --- | --- |
| **Statement** | Deleting an appeal also deletes its extension rows, deletes its linked schedule when present, recalculates the most-recent hearing sequence, and may repopulate case status or file location when the deleted appeal changed review-level or attorney/file-location state. |
| **Trigger** | `pk80001_legalnet.deleteappeal` runs. |
| **Enforcement** | `WCIS_DBA.pk80001_legalnet.deleteappeal` |
| **Outcome** | Appeal removal does not leave extension, schedule, or stale case/file-state artifacts behind. |
| **Tables** | [APPEAL](database-tables.md#appeal), [APPEAL_EXTENSION](database-tables.md#appeal_extension), [SCHEDULE](database-tables.md#schedule), [LEGAL_FILE_LOCATION](database-tables.md#legal_file_location) |
| **Source** | Oracle retrieval JSON `pk80001_legalnet.json` (`deleteappeal`) |

---

## BR-CLM-LGL-029 Hearing sequence fallback prefers consolidated HEAR then direct HEAR then other hearing-like schedules

| Field | Value |
| --- | --- |
| **Statement** | Recalculation of `most_recent_hearing_seq_num` prefers a consolidated primary-case `HEAR` row, then the case's own `HEAR` row, and finally `CCALL`, `INCON`, or `MED` rows if no `HEAR` row exists. |
| **Trigger** | `pk80001_legalnet.updateHearingSeqNum` runs. |
| **Enforcement** | `WCIS_DBA.pk80001_legalnet.updateHearingSeqNum` |
| **Outcome** | A legal case keeps the best available hearing pointer even when standard hearing rows are absent. |
| **Tables** | [LEGAL_CASE](database-tables.md#legal_case), [SCHEDULE](database-tables.md#schedule), [CONSOLIDATED_CASE](database-tables.md#consolidated_case) |
| **Source** | Oracle retrieval JSON `pk80001_legalnet.json` (`updateHearingSeqNum`) |

---

## BR-CLM-LGL-030 Schedule retrieval includes consolidated-primary schedules for secondary cases

| Field | Value |
| --- | --- |
| **Statement** | `pk80001_legalnet.getSchedule` returns direct schedule rows for the case plus primary-case schedule rows when the requested case is a consolidated secondary case. |
| **Trigger** | The library retrieves schedule data for a legal case. |
| **Enforcement** | `WCIS_DBA.pk80001_legalnet.getSchedule` |
| **Outcome** | Consolidated secondary cases expose primary hearing activity in the returned schedule recordset. |
| **Tables** | [SCHEDULE](database-tables.md#schedule), [CONSOLIDATED_CASE](database-tables.md#consolidated_case) |
| **Source** | Oracle retrieval JSON `pk80001_legalnet.json` (`getSchedule`) |

---

## BR-CLM-LGL-031 Mail and acknowledgement updates are type-driven

| Field | Value |
| --- | --- |
| **Statement** | `pk80001_legalnet.setMailDate` updates `oar_mailed_date` only for `OAR` requests and otherwise updates `recon_packet_received_date`, while `pk80001_legalnet.updateAcknowledged` only updates WCB or DCBS identifiers plus `acknowledge_date`. |
| **Trigger** | The library invokes mail-date or acknowledgement updates. |
| **Enforcement** | `WCIS_DBA.pk80001_legalnet.setMailDate`, `WCIS_DBA.pk80001_legalnet.updateAcknowledged` |
| **Outcome** | Correspondence updates modify only the identifier/date columns associated with the caller's declared type. |
| **Tables** | [LEGAL_CASE](database-tables.md#legal_case) |
| **Source** | Oracle retrieval JSON `pk80001_legalnet.json` (`setMailDate`, `updateAcknowledged`) |

---

## BR-CLM-LGL-032 Assignment only succeeds when every blocker count is zero

| Field | Value |
| --- | --- |
| **Statement** | `pk80005_assignment.assignIt` and `assignItBalanced` only assign an attorney when the sum of conflict, workload, holiday, vacation, and location blocker counts is zero. |
| **Trigger** | The assignment engine evaluates a candidate attorney. |
| **Enforcement** | `WCIS_DBA.pk80005_assignment.assignIt`, `WCIS_DBA.pk80005_assignment.assignItBalanced` |
| **Outcome** | Successful assignments write a `CA` result, update the schedule, and move the legal case to status `ASSGN`; otherwise the case remains unassigned for that candidate. |
| **Tables** | [SCHEDULE](database-tables.md#schedule), [LEGAL_CASE](database-tables.md#legal_case) |
| **Source** | Oracle retrieval JSON `pk80005_assignment.json` (`assignIt`, `assignItBalanced`) |

---

## BR-CLM-LGL-033 Weekly load thresholds vary by attorney load percent

| Field | Value |
| --- | --- |
| **Statement** | When weekly-load checking is enabled, attorneys with load percent below 34 are capped at one hearing day, attorneys below 67 at two, and all others at three before load blocks assignment. |
| **Trigger** | `pk80005_assignment.assignIt` runs with `weekly_case_load > 0`. |
| **Enforcement** | `WCIS_DBA.pk80005_assignment.assignIt` |
| **Outcome** | Lower-capacity attorneys reach load-based assignment rejection sooner than higher-capacity attorneys. |
| **Source** | Oracle retrieval JSON `pk80005_assignment.json` (`assignIt`) |

---

## BR-CLM-LGL-034 Rotation assignment only targets pending unassigned hearing rows in active rotation coverage

| Field | Value |
| --- | --- |
| **Statement** | Rotation assignment evaluates only `PENDA` cases with unassigned `HEAR` schedule rows in `SET` or `RESET` status, an active matching out-of-town rotation row, and no recon issue on the case. |
| **Trigger** | `pk80005_assignment.assign_rotation_cases` runs. |
| **Enforcement** | `WCIS_DBA.pk80005_assignment.assign_rotation_cases` |
| **Outcome** | Rotation logic skips already-assigned, outside-counsel, or recon-issue hearings. |
| **Tables** | [LEGAL_CASE](database-tables.md#legal_case), [SCHEDULE](database-tables.md#schedule), [OUT_OF_TOWN_ROTATION_ASSGN](database-tables.md#out_of_town_rotation_assgn), [REQUEST_ISSUE](database-tables.md#request_issue) |
| **Source** | Oracle retrieval JSON `pk80005_assignment.json` (`assign_rotation_cases`) |

---

## BR-CLM-LGL-035 Conflict and load helper functions treat missing data as zero blockers

| Field | Value |
| --- | --- |
| **Statement** | Conflict and load helper functions normalize `NO_DATA_FOUND` and null aggregate results to zero so missing related rows do not fail assignment evaluation. |
| **Trigger** | Helper functions such as `adjuster_conflict_check`, `employer_conflict_check`, `calendar_conflict_check`, `case_load`, or `get_weekly_case_load` run. |
| **Enforcement** | `WCIS_DBA.pk80005_assignment.adjuster_conflict_check`, `employer_conflict_check`, `alj_conflict_check`, `attorney_conflict_check`, `calendar_conflict_check`, `case_load`, `get_weekly_case_load` |
| **Outcome** | Candidate evaluation treats missing supporting rows as no blocker rather than an error condition. |
| **Source** | Oracle retrieval JSON `pk80005_assignment.json` |

---

## BR-CLM-LGL-036 Calendar review filters to active attorney profiles and requested coverage locations

| Field | Value |
| --- | --- |
| **Statement** | `pk80005_assignment.calendar_review` only reports active attorney profiles and, unless the caller requests `ALL`, only attorneys whose primary, secondary, or tertiary hearing-location code matches the requested location. |
| **Trigger** | Quick-calendar review runs. |
| **Enforcement** | `WCIS_DBA.pk80005_assignment.calendar_review` |
| **Outcome** | Calendar review shows current attorney coverage for the selected location scope. |
| **Tables** | [legal.attorney_profile](database-tables.md#legal.attorney_profile), [SCHEDULE](database-tables.md#schedule), [HEARING_LOCATION](database-tables.md#hearing_location) |
| **Source** | Oracle retrieval JSON `pk80005_assignment.json` (`calendar_review`) |

---

## BR-CLM-LGL-037 Assignment result reporting keeps the latest result per case in scope

| Field | Value |
| --- | --- |
| **Statement** | `pk80005_assignment.get_assign_results` reports only the latest assignment-result row per legal case for the requested sequence or date scope and separates assigned (`CA`, `CAC`) from non-assigned result rows. |
| **Trigger** | Assignment-process reporting requests a result feed. |
| **Enforcement** | `WCIS_DBA.pk80005_assignment.get_assign_results` |
| **Outcome** | Downstream reporting sees the terminal assignment outcome for each case instead of intermediate attempts. |
| **Tables** | `ASSIGNMENT_RESULT`, [SCHEDULE](database-tables.md#schedule), [LEGAL_CASE](database-tables.md#legal_case) |
| **Source** | Oracle retrieval JSON `pk80005_assignment.json` (`get_assign_results`) |

---

## Stored procedure business rules

Oracle source retrieval confirmed server-side rule logic in `pk80001_legalnet` and `pk80005_assignment`. The table below cross-links each extracted rule to the package page that documents the supporting PL/SQL.

| Rule ID | Rule | Source | Link |
| --- | --- | --- | --- |
| [BR-CLM-LGL-026](#br-clm-lgl-026-legal-case-search-falls-through-case-number-hierarchy) | Legal case search falls through case number hierarchy | `pk80001_legalnet.findCase` | [Details](procedures/pk80001_legalnet.md#br-clm-lgl-026-legal-case-search-falls-through-case-number-hierarchy) |
| [BR-CLM-LGL-027](#br-clm-lgl-027-case-status-propagates-to-consolidated-secondary-cases) | Case status propagates to consolidated secondary cases | `pk80001_legalnet.updateCaseStatus` | [Details](procedures/pk80001_legalnet.md#br-clm-lgl-027-case-status-propagates-to-consolidated-secondary-cases) |
| [BR-CLM-LGL-028](#br-clm-lgl-028-appeal-deletion-cascades-schedule-and-state-cleanup) | Appeal deletion cascades schedule and state cleanup | `pk80001_legalnet.deleteappeal` | [Details](procedures/pk80001_legalnet.md#br-clm-lgl-028-appeal-deletion-cascades-schedule-and-state-cleanup) |
| [BR-CLM-LGL-029](#br-clm-lgl-029-hearing-sequence-fallback-prefers-consolidated-hear-then-direct-hear-then-other-hearing-like-schedules) | Hearing sequence fallback prefers consolidated HEAR then direct HEAR then other hearing-like schedules | `pk80001_legalnet.updateHearingSeqNum` | [Details](procedures/pk80001_legalnet.md#br-clm-lgl-029-hearing-sequence-fallback-prefers-consolidated-hear-then-direct-hear-then-other-hearing-like-schedules) |
| [BR-CLM-LGL-030](#br-clm-lgl-030-schedule-retrieval-includes-consolidated-primary-schedules-for-secondary-cases) | Schedule retrieval includes consolidated-primary schedules for secondary cases | `pk80001_legalnet.getSchedule` | [Details](procedures/pk80001_legalnet.md#br-clm-lgl-030-schedule-retrieval-includes-consolidated-primary-schedules-for-secondary-cases) |
| [BR-CLM-LGL-031](#br-clm-lgl-031-mail-and-acknowledgement-updates-are-type-driven) | Mail and acknowledgement updates are type-driven | `pk80001_legalnet.setMailDate`, `updateAcknowledged` | [Details](procedures/pk80001_legalnet.md#br-clm-lgl-031-mail-and-acknowledgement-updates-are-type-driven) |
| [BR-CLM-LGL-032](#br-clm-lgl-032-assignment-only-succeeds-when-every-blocker-count-is-zero) | Assignment only succeeds when every blocker count is zero | `pk80005_assignment.assignIt`, `assignItBalanced` | [Details](procedures/pk80005_assignment.md#br-clm-lgl-032-assignment-only-succeeds-when-every-blocker-count-is-zero) |
| [BR-CLM-LGL-033](#br-clm-lgl-033-weekly-load-thresholds-vary-by-attorney-load-percent) | Weekly load thresholds vary by attorney load percent | `pk80005_assignment.assignIt` | [Details](procedures/pk80005_assignment.md#br-clm-lgl-033-weekly-load-thresholds-vary-by-attorney-load-percent) |
| [BR-CLM-LGL-034](#br-clm-lgl-034-rotation-assignment-only-targets-pending-unassigned-hearing-rows-in-active-rotation-coverage) | Rotation assignment only targets pending unassigned hearing rows in active rotation coverage | `pk80005_assignment.assign_rotation_cases` | [Details](procedures/pk80005_assignment.md#br-clm-lgl-034-rotation-assignment-only-targets-pending-unassigned-hearing-rows-in-active-rotation-coverage) |
| [BR-CLM-LGL-035](#br-clm-lgl-035-conflict-and-load-helper-functions-treat-missing-data-as-zero-blockers) | Conflict and load helper functions treat missing data as zero blockers | `pk80005_assignment` helper functions | [Details](procedures/pk80005_assignment.md#br-clm-lgl-035-conflict-and-load-helper-functions-treat-missing-data-as-zero-blockers) |
| [BR-CLM-LGL-036](#br-clm-lgl-036-calendar-review-filters-to-active-attorney-profiles-and-requested-coverage-locations) | Calendar review filters to active attorney profiles and requested coverage locations | `pk80005_assignment.calendar_review` | [Details](procedures/pk80005_assignment.md#br-clm-lgl-036-calendar-review-filters-to-active-attorney-profiles-and-requested-coverage-locations) |
| [BR-CLM-LGL-037](#br-clm-lgl-037-assignment-result-reporting-keeps-the-latest-result-per-case-in-scope) | Assignment result reporting keeps the latest result per case in scope | `pk80005_assignment.get_assign_results` | [Details](procedures/pk80005_assignment.md#br-clm-lgl-037-assignment-result-reporting-keeps-the-latest-result-per-case-in-scope) |

## Notes
- Statements marked with `*` were inferred from code structure, naming conventions, or partial excerpt evidence where
  direct confirmation was not available in source artifacts (per TSK004/TSK1B-002 confidence markers).
- Statements marked with `†` were retrieved from dependency library documentation via the Legends CLI RAG service
  (`SAIF.Framework.Core` base-class behavior), consistent with the inherited-content requirements for this library
  (frameworkDensity = 96).
- `clsAttorneyConflict` and `clsAttorneyWorkerAssignment` were confirmed to have empty `AddBusinessRules()` bodies —
  no rules enforced beyond framework-level required-field/CRUD-failure handling.

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Architecture](architecture.md)
- [Dependencies](dependencies.md)
- [Operations and processes](operations-processes.md)
- [Database tables](database-tables.md)
- [SQL catalog](sql/index.md)
- [API reference](api/index.md)

## Sources
- `SAIF.Business.Claim.Legal\LegalNet\` (clsCaseCost.vb, clsCaseSearchCriteria.vb, clsLegalFileLocation.vb, clsConsolidations.vb, clsLegalSchedule.vb)
- `SAIF.Business.Claim.Legal\TableMaint\` (clsAttorneyWorkerAssignment.vb, clsAttorneyProfile.vb, clsHearingLocation.vb, clsLegalPerson.vb, clsLegalPersonType.vb, clsOtherFirm.vb, clsOutOFTownRotationAssgn.vb)
- `SAIF.Business.Claim.Legal\Print\clsLetterRequest.vb`
